package cloud.tianai.mate.captcha.generator.impl;

import cloud.tianai.captcha.generator.AbstractImageCaptchaGenerator;
import cloud.tianai.captcha.generator.ImageTransform;
import cloud.tianai.captcha.generator.common.model.dto.*;
import cloud.tianai.captcha.generator.common.util.CaptchaImageUtils;
import cloud.tianai.captcha.interceptor.CaptchaInterceptor;
import cloud.tianai.captcha.resource.ImageCaptchaResourceManager;
import cloud.tianai.captcha.resource.common.model.dto.Resource;
import cloud.tianai.captcha.resource.common.model.dto.ResourceMap;
import cloud.tianai.mate.captcha.common.constant.MateCaptchaTypeConstant;

import java.awt.*;
import java.awt.image.BufferedImage;

/**
 * @Author: 天爱有情
 * @date 2024/6/15 14:43
 * @Description 滑块验证码-仿网易
 */
public class MateSlider2ImageCaptchaGenerator extends AbstractImageCaptchaGenerator {

    /** 模板滑块固定名称. */
    public static String TEMPLATE_ACTIVE_IMAGE_NAME = "active.png";
    /** 模板凹槽固定名称. */
    public static String TEMPLATE_FIXED_IMAGE_NAME = "fixed.png";

    public MateSlider2ImageCaptchaGenerator() {
    }

    public MateSlider2ImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager) {
        super(imageCaptchaResourceManager);
    }

    public MateSlider2ImageCaptchaGenerator(ImageCaptchaResourceManager imageCaptchaResourceManager, ImageTransform imageTransform, CaptchaInterceptor interceptor) {
        super(imageCaptchaResourceManager);
        setImageTransform(imageTransform);
        setInterceptor(interceptor);
    }

    @Override
    protected void doInit() {
//        ResourceStore resourceStore = imageCaptchaResourceManager.getResourceStore();
//        // 添加一些系统的资源文件
//        resourceStore.addResource(MateCaptchaTypeConstant.SLIDER2, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_RESOURCE_PATH.concat("/1.jpg"), DEFAULT_TAG));
//
//        // 添加一些系统的 模板文件
//        ResourceMap template1 = new ResourceMap(DEFAULT_TAG, 4);
//        template1.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/active.png")));
//        template1.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/1/fixed.png")));
//        resourceStore.addTemplate(MateCaptchaTypeConstant.SLIDER2, template1);
//
//        ResourceMap template2 = new ResourceMap(DEFAULT_TAG, 4);
//        template2.put(TEMPLATE_ACTIVE_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/active.png")));
//        template2.put(TEMPLATE_FIXED_IMAGE_NAME, new Resource(ClassPathResourceProvider.NAME, DEFAULT_SLIDER_IMAGE_TEMPLATE_PATH.concat("/2/fixed.png")));
//        resourceStore.addTemplate(MateCaptchaTypeConstant.SLIDER2, template2);
    }

    @Override
    protected void doGenerateCaptchaImage(CaptchaExchange captchaExchange) {
        GenerateParam param = captchaExchange.getParam();
        Boolean obfuscate = param.getObfuscate();
        ResourceMap templateResource = requiredRandomGetTemplate(param.getType(), param.getTemplateImageTag());
        Resource resourceImage = requiredRandomGetResource(param.getType(), param.getBackgroundImageTag());
        BufferedImage background = getResourceImage(resourceImage);
        BufferedImage fixedTemplate = getTemplateImage(templateResource, TEMPLATE_FIXED_IMAGE_NAME);
        BufferedImage activeTemplate = getTemplateImage(templateResource, TEMPLATE_ACTIVE_IMAGE_NAME);

        // 旋转起点为上还是下
        boolean topOrBottom = randomBoolean();
        int maxRandomX = background.getWidth() - fixedTemplate.getWidth() - 10;
        int minRandomX = fixedTemplate.getWidth() + 5;
        int minRandomY = 0;
        int maxRandomY = background.getHeight() - fixedTemplate.getHeight();
        int minRotate = 30;
        int maxRotate = 80;
        int randomX = randomInt(minRandomX, maxRandomX);
        int randomY = randomInt(minRandomY, maxRandomY);
        double rate = (background.getWidth() - background.getHeight() - fixedTemplate.getWidth()) / (double) background.getWidth();
        int calcRandomX = (int) (randomX * rate);
        // -80~80
        int rotate = randomInt(minRotate, maxRotate);
        int rotateX = fixedTemplate.getWidth() + calcRandomX;
        int rotateY = background.getHeight();

        if (topOrBottom) {
            rotateY = 0;
            rotate = -rotate;
        }

        // 滑块
        BufferedImage matrixTemplate = CaptchaImageUtils.createTransparentImage(activeTemplate.getWidth(), background.getHeight());
        CaptchaImageUtils.overlayImage(matrixTemplate, activeTemplate, 0, randomY);

        if (obfuscate) {
            // 随机移动 x 和 y， 使其不重叠
            int obfuscateX = randomX > (maxRandomX / 2) ? randomInt(minRandomX, randomX - minRandomX) : randomInt(randomX + minRandomX, maxRandomX);
            int obfuscateY = randomY > maxRandomY / 2 ? randomInt(minRandomY, randomY - fixedTemplate.getHeight()) : randomInt(randomY + fixedTemplate.getHeight(), maxRandomY);
            int obfuscateRotate = Math.abs(rotate) > maxRotate / 2 ? randomInt(minRotate / 2, Math.abs(rotate)) : randomInt(Math.abs(rotate), maxRotate);
            if (topOrBottom) {
                obfuscateRotate = -obfuscateRotate;
            }

            // 改为随机抠图
            BufferedImage cutImage = CaptchaImageUtils.cutImage(background, fixedTemplate, randomInt(minRandomX, maxRandomX), randomInt(minRandomY, maxRandomY));
            CaptchaImageUtils.overlayImage(matrixTemplate, cutImage, 0, randomY);

            Graphics2D obG2d = background.createGraphics();
            obG2d.rotate(Math.toRadians(obfuscateRotate), fixedTemplate.getWidth() + (obfuscateX * rate), rotateY);

//            BufferedImage b2 = CaptchaImageUtils.createTransparentImage(fixedTemplate.getWidth(), background.getHeight());
//            Graphics2D b2d = b2.createGraphics();
//            b2d.setColor(Color.black);
//            b2d.drawRect(0, 0, b1.getWidth() - 2, b1.getHeight() - 2);
//            b2d.dispose();
//            CaptchaImageUtils.overlayImage(b2, fixedTemplate, 0, obfuscateY);
//            obG2d.drawImage(b2, (int) (obfuscateX * rate), 0, null);

            obG2d.drawImage(fixedTemplate, (int) (obfuscateX * rate), obfuscateY, null);
            obG2d.dispose();

        } else {
            BufferedImage maskImage = CaptchaImageUtils.createTransparentImage(background.getWidth(), background.getHeight());
            Graphics2D graphics = maskImage.createGraphics();
//            graphics.drawRect(0, 0, bgMask1.getWidth() - 2, bgMask1.getHeight() - 2);
            graphics.rotate(Math.toRadians(rotate), rotateX, rotateY);

//            BufferedImage b1 = CaptchaImageUtils.createTransparentImage(fixedTemplate.getWidth(), background.getHeight());
//            Graphics2D b1d = b1.createGraphics();
//            b1d.setColor(Color.black);
//            b1d.drawRect(0, 0, b1.getWidth() - 2, b1.getHeight() - 2);
//            b1d.dispose();
//            CaptchaImageUtils.overlayImage(b1, fixedTemplate, 0, randomY);
//            graphics.drawImage(b1, calcRandomX, 0, null);

            graphics.drawImage(fixedTemplate, calcRandomX, randomY, null);
            graphics.dispose();
            BufferedImage cutImage = CaptchaImageUtils.cutImage(background, maskImage, 0, 0);
            Graphics2D graphics3 = matrixTemplate.createGraphics();
            graphics3.translate(-calcRandomX, 0);
            graphics3.rotate(Math.toRadians(-rotate), rotateX, rotateY);
            graphics3.drawImage(cutImage, 0, 0, null);
            graphics3.dispose();
            CaptchaImageUtils.overlayImage(matrixTemplate, cutImage, 0, randomY);
        }
        CaptchaImageUtils.overlayImage(matrixTemplate, activeTemplate, 0, randomY);
        // 背景图
        Graphics2D bG2d = background.createGraphics();
        bG2d.rotate(Math.toRadians(rotate), rotateX, rotateY);
        bG2d.drawImage(fixedTemplate, calcRandomX, randomY, null);
        bG2d.dispose();
        double rotatePercentage = ((double) rotate / ((double) calcRandomX / background.getWidth()));
        TransferData transferData = new TransferData();
        transferData.x = randomX;
        transferData.calcX = calcRandomX;
        transferData.y = randomY;
        transferData.rotatePercentage = rotatePercentage;
        captchaExchange.setBackgroundImage(background);
        captchaExchange.setTemplateImage(matrixTemplate);
        captchaExchange.setTemplateResource(templateResource);
        captchaExchange.setResourceImage(resourceImage);
        captchaExchange.setTransferData(transferData);
        captchaExchange.getCustomData().putViewData("attr", rotatePercentage);
    }

    public static class TransferData {
        int x;
        int calcX;
        int y;
        double rotatePercentage;

    }

    @Override
    protected ImageCaptchaInfo doWrapImageCaptchaInfo(CaptchaExchange captchaExchange) {
        GenerateParam param = captchaExchange.getParam();
        BufferedImage backgroundImage = captchaExchange.getBackgroundImage();
        BufferedImage sliderImage = captchaExchange.getTemplateImage();
        Resource resourceImage = captchaExchange.getResourceImage();
        ResourceMap templateResource = captchaExchange.getTemplateResource();
        CustomData customData = captchaExchange.getCustomData();
        TransferData data = (TransferData) captchaExchange.getTransferData();
        ImageTransformData transform = getImageTransform().transform(param, backgroundImage, sliderImage, resourceImage, templateResource, customData);

        ImageCaptchaInfo imageCaptchaInfo = new ImageCaptchaInfo();
        imageCaptchaInfo.setBackgroundImageHeight(backgroundImage.getHeight());
        imageCaptchaInfo.setBackgroundImageWidth(backgroundImage.getWidth());
        imageCaptchaInfo.setBackgroundImage(transform.getBackgroundImageUrl());
        imageCaptchaInfo.setBackgroundImageTag(resourceImage.getTag());

        imageCaptchaInfo.setTemplateImageWidth(sliderImage.getWidth());
        imageCaptchaInfo.setTemplateImageHeight(sliderImage.getHeight());
        imageCaptchaInfo.setTemplateImage(transform.getTemplateImageUrl());
        imageCaptchaInfo.setTemplateImageTag(templateResource.getTag());

        imageCaptchaInfo.setRandomX(data.x);
        imageCaptchaInfo.setData(customData);
        imageCaptchaInfo.setType(MateCaptchaTypeConstant.SLIDER2);
        return imageCaptchaInfo;
    }
}

